﻿using com.yoozoo.gta.Gameplay.PVE;
using com.yoozoo.gta.Gameplay.PVE.Editor;
using Gameplay.PVE;
using LogSystem;
using NpcFramework;
using NpcFramework.Traffic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.AssetStandardProcessors;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using Yoozoo.Core.Extensions.CSharp;
using Yoozoo.Core.Extensions.Engine;
using Yoozoo.Gameplay.SceneSeparate;

namespace Yoozoo.Gameplay.City.Editor
{
    [CustomEditor(typeof(CitySceneSeparateManager))]
    public class CitySceneSeparateManagerEditor : UnityEditor.Editor
    {
        private const string sceneRootPath = "Assets/ResourcesAssets/City/Scenes/";

        private static readonly string[] levelUpMarkerNames = {
            "mesh_innercity_props_zhishipai_01",
            "mesh_innercity_props_zhishipai_02",
            "mesh_innercity_props_jiantou_01"
        };

        private CitySceneSeparateManager m_Target;
        private GgameSceneConfig mapData;
        private UnityEditor.Editor cacheEditor;

        void OnEnable()
        {
            m_Target = target as CitySceneSeparateManager;
        }

        private void ExportCity(string mapConfigName)
        {
            if (m_Target.transform.childCount != 0)
            {
                EditorUtility.DisplayDialog("Error", "当前物体下有子物体,请删除~", "ok");
                return;
            }

            if (string.IsNullOrEmpty(mapConfigName))
            {
                EditorUtility.DisplayDialog("Error", "请填写正确的地图配置文件名", "OK");
                return;
            }

            string rootName = "[Root]";
            var root = GameObject.Find(rootName);
            if (root == null)
            {
                EditorUtility.DisplayDialog("Error", "场景里没有找到" + rootName, "OK");
                return;
            }

            AssetGraphPostprocessor.Postprocessor.Enabled = false;

            var rootTransform = root.transform;
            var roomRoot = rootTransform.Find("room");
            var roomBeforeRoot = rootTransform.Find("room_before");
            var otherRoot = rootTransform.Find("other");

            roomRoot.SetActive(true);

            // 关闭casterShadow
            TurnOffShadowCasting(roomRoot, m_Target.NonCasterShadowRoot);

            if (m_Target.CreateVariantAfterExport)
            {
                // room_before和other下的预制体都不导出
                roomBeforeRoot.SetActive(false);
                otherRoot.SetActive(false);
            }
            else
            {
                // room_before, event 下关闭升级指示牌
                // room_before本身可能是想做出差异来，但现在美术资源没有跟上，目前用的就是room
                // 而且现在需要根据room维护room_before，同步光照，反射探针
                // event里面也有4个 event_rts_xx，也是这个情况

                roomBeforeRoot.SetActive(true);
                otherRoot.SetActive(true);
                TurnOffShadowCasting(roomBeforeRoot, m_Target.NonCasterShadowRoot);
                TurnOffShadowCasting(otherRoot, m_Target.NonCasterShadowRoot);

                if (roomBeforeRoot)
                    TurnOffLevelUpMarker(roomBeforeRoot);
                
                if (otherRoot)
                    TurnOffLevelUpMarker(otherRoot);
            }

            string prefabRootPath = $"{sceneRootPath}{mapConfigName}/Prefabs";
            if (!Directory.Exists(prefabRootPath))
                Directory.CreateDirectory(prefabRootPath);

            bool lod1 = false;
            bool renderSetting = true;
            bool exportScene = false;

            SceneConfigExporter.onStartExport = null;
            SceneConfigExporter.additionalAction = null;

            SceneConfigExporter.Export(rootName, mapConfigName, renderSetting, sceneRootPath);

            // 直接复制非烘焙的预制体
            foreach (var prefabInfo in m_Target.PrefabInfos)
            {
                // 烘焙过的预制体走导出流程
                if (prefabInfo.IsLightMapped)
                    continue;
                
                var oldPath = prefabInfo.AssetPath;
                var newPath = $"{prefabRootPath}/{prefabInfo.PrefabName}.prefab";
                bool success = AssetDatabase.CopyAsset(oldPath, newPath);
                if(!success)
                {
                    Debug.LogErrorFormat(LogModule.City, "复制文件出错: {0} => {1}", oldPath, newPath);
                }
            }

            AssetDatabase.Refresh();

            if (m_Target.CreateVariantAfterExport)
            {
                // 创建变体
                foreach (var prefabInfo in m_Target.PrefabInfos)
                {
                    if (!prefabInfo.IsVariant)
                        continue;
                    
                    var targetPrefabPath = $"{prefabRootPath}/{prefabInfo.PrefabName}.prefab";
                    var rawPrefabPath = $"{prefabRootPath}/{prefabInfo.RawPrefabName}.prefab";
                    var prefabContents = PrefabUtility.LoadPrefabContents(rawPrefabPath);
                    
                    // 关闭升级标记
                    TurnOffLevelUpMarker(prefabContents.transform);

                    // 保存成变体
                    PrefabUtility.SaveAsPrefabAsset(prefabContents, rawPrefabPath);
                    PrefabUtility.SaveAsPrefabAsset(prefabContents, targetPrefabPath);
                }
            }

            string configPath = $"{sceneRootPath}{mapConfigName}.asset";
            var config = AssetDatabase.LoadAssetAtPath<ScriptableObject>(configPath) as GgameSceneConfig;
            config.PrefabPaths = new List<string>();
            foreach (var prefabInfo in m_Target.PrefabInfos)
            {
                config.PrefabPaths.Add($"{prefabRootPath}/{prefabInfo.PrefabName}.prefab");
            }

            EditorUtility.SetDirty(config);
            AssetDatabase.SaveAssets();

            SceneConfigExporter.additionalAction = null;
            SceneConfigExporter.onStartExport = null;
            EditorUtility.ClearProgressBar();

            m_Target.sceneData = null;
            EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());

            AssetGraphPostprocessor.Postprocessor.Enabled = true;
        }

        /// <summary>
        /// 关闭 parent 节点下，所有名为 levelUpMarkerName 的物件
        /// </summary>
        /// <param name="parent"></param>
        private void TurnOffLevelUpMarker(Transform parent)
        {
            if (levelUpMarkerNames.Contains(parent.name))
            {
                parent.gameObject.SetActive(false);
            }
            else
            {
                int childCount = parent.childCount;
                for (int i = 0; i < childCount; i++)
                {
                    TurnOffLevelUpMarker(parent.GetChild(i));
                }
            }
        }

        /// <summary>
        /// 关闭名为 nonCasterShadowRoot 的节点下的所有Renderer的ShadowCast
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="nonCasterShadowRoot"></param>
        private void TurnOffShadowCasting(Transform parent, string nonCasterShadowRoot)
        {
            if (parent.name == nonCasterShadowRoot)
            {
                // 这个节点下面的所有MeshRenderer的CasterShadow关闭
                var renderers = parent.GetComponentsInChildren<Renderer>(true);
                foreach (var renderer in renderers)
                {
                    renderer.shadowCastingMode = ShadowCastingMode.Off;
                }
            }
            else
            {
                int childCount = parent.childCount;
                for (int i = 0; i < childCount; i++)
                {
                    TurnOffShadowCasting(parent.GetChild(i), nonCasterShadowRoot);
                }
            }
        }

        public override void OnInspectorGUI()
        {
            var mapConfigName = m_Target.mapConfigName;
            if (m_Target.showEditor)
            {
                var message = $"1. 点击【场景检查】, 没有弹窗就OK，保存场景，把场景和预制体都提交\n" +
                              $"2. 点击【导出内城房间】, 会提示预制体有修改, 不用管，点【确定】\n" +
                              $"3. 不要保存场景，也不要提交预制体!!!\n" +
                              $"4. 提交{mapConfigName}目录下的文件即可";
                EditorGUILayout.HelpBox(message, MessageType.Info);

                if (GUILayout.Button("导出内城房间", GUILayout.Height(40)))
                {
                    AssetGraphPostprocessor.Postprocessor.Enabled = false;
                    try
                    {
                        ExportCity(mapConfigName);
                    }
                    catch (Exception e)
                    {
                        UnityEngine.Debug.LogException(e);
                    }
                    finally
                    {
                        EditorUtility.ClearProgressBar();
                        AssetGraphPostprocessor.Postprocessor.Enabled = true;
                    }
                }

                if (GUILayout.Button("场景检查", GUILayout.Height(35)))
                {
                    AssetGraphPostprocessor.Postprocessor.Enabled = false;
                    try
                    {
                        CreatePrefabInfos();
                        CheckScene();
                    }
                    catch (Exception e)
                    {
                        UnityEngine.Debug.LogException(e);
                    }
                    finally
                    {
                        AssetGraphPostprocessor.Postprocessor.Enabled = true;
                    }
                    
                }
                
                var message2 = $"修改了房间预制体结构后，会出现报错：光照信息同步失败\n" +
                               $"1. 删除room_before下的所有预制体\n" +
                               $"2. 点击【创建房间变体】\n" +
                               $"3. 如果报错没有使用反射探针，IsSyncReflectionProbe设为false即可\n" +
                               $"4. 保存场景，上传场景和RoomBefore目录下的预制体";
                EditorGUILayout.HelpBox(message2, MessageType.Info);

                if (GUILayout.Button("创建房间变体", GUILayout.Height(40)))
                {
                    CreateRoomPrefabVariant();
                }

                if (GUILayout.Button("创建事件变体", GUILayout.Height(40)))
                {
                    CreateEventPrefabVariant();
                }

                GUILayout.Space(20);

                if (GUILayout.Button("生成预制体信息", GUILayout.Height(40)))
                {
                    CreatePrefabInfos();
                }

                if (GUILayout.Button("房间合图检查", GUILayout.Height(35)))
                {
                    CheckRoom();
                }

                GUILayout.Space(20);
            }

            base.OnInspectorGUI();
            GUILayout.Space(20);

            if (m_Target.sceneData)
            {
                if (cacheEditor == null)
                {
                    cacheEditor = UnityEditor.Editor.CreateEditor(m_Target.sceneData);
                }
                cacheEditor.OnInspectorGUI();
            }
        }

        /// <summary>
        /// 创建预制体信息
        /// </summary>
        private void CreatePrefabInfos()
        {
            m_Target.PrefabInfos.Clear();

            string rootName = "[Root]";
            GameObject root = GameObject.Find(rootName);
            if (root == null)
            {
                EditorUtility.DisplayDialog("错误", "没有找到场景的根节点，请保证场景中有命名为 [Root] 的根节点，Active状态为True", "关闭");
                return;
            }

            var rootTransform = root.transform;
            var roomRoot = rootTransform.Find("room");
            var roomBeforeRoot = rootTransform.Find("room_before");
            var otherRoot = rootTransform.Find("other");
            List<Transform> transforms = new List<Transform>();
            for (int i = 0; i < roomRoot.childCount; i++)
            {
                var child = roomRoot.GetChild(i);
                transforms.Add(child);
            }

            for (int i = 0; i < roomBeforeRoot.childCount; i++)
            {
                var child = roomBeforeRoot.GetChild(i);
                transforms.Add(child);
            }

            for (int i = 0; i < otherRoot.childCount; i++)
            {
                var child = otherRoot.GetChild(i);
                transforms.Add(child);
            }

            string errorMessage = "";

            foreach (var transform in transforms)
            {
                var prefab = transform.gameObject;

                var prefabAssetType = PrefabUtility.GetPrefabAssetType(prefab);
                if (prefabAssetType == PrefabAssetType.MissingAsset)
                {
                    errorMessage += $"{transform.name}掉了\n";
                    UnityEngine.Debug.LogErrorFormat(prefab, "{0}掉了", transform.name);
                    continue;
                }

                if (prefabAssetType == PrefabAssetType.Model)
                {
                    errorMessage += $"{transform.name}是一个模型\n";
                    UnityEngine.Debug.LogErrorFormat(prefab, "{0}是一个模型", transform.name);
                    continue;
                }

                if (prefabAssetType == PrefabAssetType.NotAPrefab)
                {
                    errorMessage += $"{transform.name}不是预制体\n";
                    UnityEngine.Debug.LogErrorFormat(prefab, "{0}不是预制体", transform.name);
                    continue;
                }

                string assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefab);

                if (assetPath.StartsWith(sceneRootPath))
                {
                    errorMessage += $"{assetPath}存放在导出的路径下\n";
                    continue;
                }

                var prefabName = Path.GetFileNameWithoutExtension(assetPath);
                bool isLightMapped = false;
                bool isVariant = false;
                string rawPrefabName = "";

                // InnerCity_开头的都是房间，都是烘焙过的
                if (prefabName.StartsWith("InnerCity_"))
                    isLightMapped = true;

                // _before结尾的都是房间的变体
                if (prefabName.EndsWith("_before"))
                {
                    if (m_Target.NoVariantRooms.Contains(prefabName))
                    {
                        // 部分room_before有差异，不从原预制体创建
                        isLightMapped = false;
                    }
                    else
                    {
                        isVariant = true;
                        rawPrefabName = prefabName.Replace("_before", "");
                    }
                }
                
                // 部分RTS事件是特殊的，是物资房间的变体，也是烘焙过的
                if (m_Target.VariantPrefabs.Contains(prefabName))
                {
                    isLightMapped = true;
                    isVariant = true;
                    var variantInfo = m_Target.VariantInfos.Find(x => x.VariantName == prefabName);
                    if (variantInfo != null)
                        rawPrefabName = variantInfo.PrefabName;
                }

                m_Target.PrefabInfos.Add(new CityScenePrefabInfo
                {
                    PrefabName = prefabName,
                    IsLightMapped = isLightMapped,
                    IsVariant = isVariant,
                    RawPrefabName = rawPrefabName,
                    AssetPath = assetPath
                });
            }

            if (!string.IsNullOrEmpty(errorMessage))
            {
                EditorUtility.DisplayDialog("错误", errorMessage, "关闭");
            }
        }

        /// <summary>
        /// 检查房间的合图情况
        /// </summary>
        private void CheckRoom()
        {
            string rootName = "[Root]";
            GameObject root = GameObject.Find(rootName);
            if (root == null)
            {
                EditorUtility.DisplayDialog("错误", "没有找到场景的根节点，请保证场景中有命名为 [Root] 的根节点，Active状态为True", "关闭");
                return;
            }

            var combinedMaterials = new List<string>()
            {
                // 合图后的统一材质
                "innercity_props_01",

                // 透明材质，用于玻璃
                "neicheng_dating_weilan02_LOD0",
                "mat_innercity_glass01",
                "neicheng_bachang_boligui01_glass_D",
                "neicheng_dating_chaji01_glass",

                // 地面，需要Repeat
                "mat_innercity_danyaozuofang_dimian_01",
            };

            var knownIssueMaterials = new List<string>()
            {
            };

            var noLightMapMaterials = new List<string>
            {
                //"mat_innercity_props_01",
                "neicheng_shadow_only_instancing",
                "mat_innercity_decal_shadow",
                "mat_innercity_props_03",

                "InnerCity_caigoukache_01",
                "InnerCity_caigoukache_glass_01",

                "mat_innercity_tvshow_01",
                "mat_innercity_shiwai_changyi_01",

                "neicheng_plant01d",
                "neicheng_plant01d_p",
                "mat_innercity_plant03",
                "mat_innercity_plant03d_p",
            };

            // 处理 [Root]/room
            var materials = new List<Material>();
            var roomRoot = root.transform.Find("room");
            int childCount = roomRoot.childCount;

            Debug.LogError(LogModule.City, "========== 检查LOD Group ==========");

            for (int i = 0; i < childCount; i++)
            {
                var child = roomRoot.GetChild(i);
                var childGameObject = child.gameObject;

                var lodGroups = childGameObject.GetComponentsInChildren<LODGroup>();

                // 不允许LOD Group, 可能造成合并LOD0，LOD1到一起
                foreach (var lodGroup in lodGroups)
                {
                    Debug.LogError(LogModule.City, $"预制体{childGameObject}使用了LODGroup({lodGroup.name})", lodGroup);
                }
            }

            Debug.LogError(LogModule.City, "========== 检查材质 ==========");
            for (int i = 0; i < childCount; i++)
            {
                var child = roomRoot.GetChild(i);
                var childGameObject = child.gameObject;
                
                var meshRendererArray = childGameObject.GetComponentsInChildren<MeshRenderer>();

                foreach (var meshRenderer in meshRendererArray)
                {
                    // 墙不检查
                    if(meshRenderer.name.Contains("_roomwall_"))
                        continue;
                    
                    if (meshRenderer.sharedMaterials == null)
                    {
                        Debug.LogError(LogModule.City, $"预制体{childGameObject}的网格({meshRenderer.name})材质掉了", meshRenderer);
                        continue;
                    }
                    
                    if (meshRenderer.lightmapIndex == -1)
                    {
                        foreach (var material in meshRenderer.sharedMaterials)
                        {
                            if (!materials.Contains(material))
                                materials.Add(material);

                            // OK
                            if (noLightMapMaterials.Contains(material.name))
                                continue;

                            // error
                            Debug.LogError(LogModule.City,
                                $"预制体{childGameObject.name}的网格({meshRenderer.name})使用了材质{material.name}", meshRenderer);
                        }
                    }
                    else
                    {
                        foreach (var material in meshRenderer.sharedMaterials)
                        {
                            if (!materials.Contains(material))
                                materials.Add(material);

                            // OK
                            if (combinedMaterials.Contains(material.name))
                                continue;

                            // warning
                            if (knownIssueMaterials.Contains(material.name))
                            {
                                Debug.LogWarning(LogModule.City,
                                    $"预制体{childGameObject.name}的网格({meshRenderer.name})使用了材质{material.name}",  LogLevelType.Develop,
                                    meshRenderer);
                                continue;
                            }

                            // error
                            Debug.LogError(LogModule.City,
                                $"预制体{childGameObject.name}的网格({meshRenderer.name})使用了材质{material.name}", meshRenderer);
                        }
                    }
                }
            }

            materials.Sort((a,b)=> string.Compare(a.name, b.name, StringComparison.Ordinal));
            var stringBuilder = new StringBuilder();
            foreach (var material in materials)
            {
                stringBuilder.AppendLine(material.name);
            }
            //Debug.LogError(LogModule.City, stringBuilder);
        }

        private void CheckScene()
        {
            string rootName = "[Root]";
            GameObject root = GameObject.Find(rootName);
            if (root == null)
            {
                EditorUtility.DisplayDialog("错误", "没有找到场景的根节点，请保证场景中有命名为 [Root] 的根节点，Active状态为True", "关闭");
                return;
            }

            HashSet<string> prefabPathSet = new HashSet<string>();

            // 处理 [Root]/room, 要求根节点下的物件打成预制体，不能有重复项，自动Apply
            // 不检查材质丢失，反射探针没有烘焙等问题，这些应该美术保证
            {
                var roomRoot = root.transform.Find("room");
                int childCount = roomRoot.childCount;
                for (int i = 0; i < childCount; i++)
                {
                    var child = roomRoot.GetChild(i);
                    var childGameObject = child.gameObject;
                    if (PrefabUtility.IsOutermostPrefabInstanceRoot(childGameObject))
                    {
                        string prefabPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(childGameObject);
                        if (prefabPathSet.Contains(prefabPath))
                        {
                            // 重复
                            var message = $"{child.name}重复放置";
                            Debug.LogError(LogModule.City, message, child);
                            EditorUtility.DisplayDialog("错误", message, "关闭");
                        }
                        else
                        {
                            prefabPathSet.Add(prefabPath);

                            // 自动Apply
                            var modifications = PrefabUtility.GetPropertyModifications(childGameObject);
                            if (modifications.IsNotEmpty())
                            {
                                PrefabUtility.ApplyPrefabInstance(childGameObject, InteractionMode.AutomatedAction);
                            }

                            var meshFilters = childGameObject.GetComponentsInChildren<MeshFilter>();
                            foreach (var meshFilter in meshFilters)
                            {
                                if (meshFilter.sharedMesh == null)
                                {
                                    var message = $"{meshFilter.name}上的网格掉了";
                                    UnityEngine.Debug.LogError(message, meshFilter);
                                    EditorUtility.DisplayDialog("错误", message, "关闭");
                                }
                            }
                        }
                    }
                    else
                    {
                        var message = $"{child.name}不是预制体";
                        Debug.LogError(LogModule.City, message, child);
                        EditorUtility.DisplayDialog("错误", message, "关闭");
                    }
                }
            }

            if(!m_Target.CreateVariantAfterExport)
            {
                var roomRoot = root.transform.Find("room_before");
                int childCount = roomRoot.childCount;
                for (int i = 0; i < childCount; i++)
                {
                    var child = roomRoot.GetChild(i);
                    var childGameObject = child.gameObject;
                    if (PrefabUtility.IsOutermostPrefabInstanceRoot(childGameObject))
                    {
                        string prefabPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(childGameObject);
                        if (prefabPathSet.Contains(prefabPath))
                        {
                            // 重复
                            var message = $"{child.name}重复放置";
                            Debug.LogError(LogModule.City, message, child);
                            EditorUtility.DisplayDialog("错误", message, "关闭");
                        }
                        else
                        {
                            prefabPathSet.Add(prefabPath);

                            var lightSync = childGameObject.GetOrAddComponent<CityLightMapSync>();
                            if (lightSync.Sync())
                            {
                                // 自动Apply
                                var modifications = PrefabUtility.GetPropertyModifications(childGameObject);
                                if (modifications.IsNotEmpty())
                                {
                                    PrefabUtility.ApplyPrefabInstance(childGameObject, InteractionMode.AutomatedAction);
                                }
                            }
                            else
                            {
                                // Mesh对不齐，重新导出
                                var message = $"{child.name}结构不一致";
                                Debug.LogError(LogModule.City, message, child);
                                EditorUtility.DisplayDialog("错误", message, "关闭");
                            }
                        }
                    }
                    else
                    {
                        var message = $"{child.name}不是预制体";
                        Debug.LogError(LogModule.City, message, child);
                        EditorUtility.DisplayDialog("错误", message, "关闭");
                    }
                }
            }

            EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
        }

        private void CreateRoomPrefabVariant()
        {
            var rootObj = GameObject.Find("[Root]");
            if (rootObj == null)
                return;

            var rootTransform = rootObj.transform;
            var roomTransform = rootTransform.Find("room");
            if (roomTransform == null)
                return;

            var variantRootName = "room_before";
            var variantRoot = rootTransform.Find(variantRootName);
            if (variantRoot == null)
            {
                var go = new GameObject(variantRootName);
                variantRoot = go.transform;
                variantRoot.SetParent(rootTransform);
                variantRoot.LocalReset();
                variantRoot.SetLocalPositionX(200);
            }

            for (int i = 0; i < roomTransform.childCount; i++)
            {
                var child = roomTransform.GetChild(i);
                var childGameObject = child.gameObject;
                var isOutermostPrefabInstanceRoot = PrefabUtility.IsOutermostPrefabInstanceRoot(childGameObject);
                var isInnerCityRoom = child.name.StartsWith("InnerCity_");
                if (isOutermostPrefabInstanceRoot && isInnerCityRoom)
                {
                    // 创建预制体变体，挂上 CityLightMapSync， 并指向本体
                    string assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(childGameObject);
                    var asset = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
                    var instanceRoot = PrefabUtility.InstantiatePrefab(asset) as GameObject;
                    if (instanceRoot == null)
                        continue;

                    instanceRoot.SetParent(variantRoot);
                    var instanceRootTransform = instanceRoot.transform;
                    instanceRootTransform.localPosition = child.localPosition;
                    instanceRootTransform.localScale = child.localScale;
                    instanceRootTransform.localEulerAngles = child.localEulerAngles;
                    var cityLightMapSync = instanceRoot.AddComponent<CityLightMapSync>();
                    cityLightMapSync.originRoot = child;
                    cityLightMapSync.IsSyncReflectionProbe = true;

                    string fileName = Path.GetFileNameWithoutExtension(assetPath);
                    instanceRoot.name = $"{fileName}_before";
                    PrefabUtility.SaveAsPrefabAssetAndConnect(instanceRoot,
                        $"Assets/Arts/Scene/InnerCity/Prefabs/RoomBefore/{fileName}_before.prefab", InteractionMode.AutomatedAction);
                }
            }

            EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
        }

        private void CreateEventPrefabVariant()
        {
            var rootObj = GameObject.Find("[Root]");
            if (rootObj == null)
                return;

            var rootTransform = rootObj.transform;
            var roomTransform = rootTransform.Find("room");
            if (roomTransform == null)
                return;

            var variantRootName = "other";
            var beforeTransform = rootTransform.Find(variantRootName);
            if (beforeTransform == null)
            {
                var go = new GameObject(variantRootName);
                beforeTransform = go.transform;
                beforeTransform.SetParent(rootTransform);
                beforeTransform.LocalReset();
                beforeTransform.SetLocalPositionX(200);
            }
            
            for (int i = 0; i < roomTransform.childCount; i++)
            {
                var child = roomTransform.GetChild(i);
                var childGameObject = child.gameObject;
                var isOutermostPrefabInstanceRoot = PrefabUtility.IsOutermostPrefabInstanceRoot(childGameObject);
                var variantInfo = m_Target.VariantInfos.Find(x => x.PrefabName == child.name);

                if (isOutermostPrefabInstanceRoot && variantInfo != null)
                {
                    // 创建预制体变体，挂上 CityLightMapSync， 并指向本体
                    string assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(childGameObject);
                    var asset = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
                    var instanceRoot = PrefabUtility.InstantiatePrefab(asset) as GameObject;
                    if(instanceRoot == null)
                        continue;

                    instanceRoot.SetParent(beforeTransform);
                    var instanceRootTransform = instanceRoot.transform;
                    instanceRootTransform.localPosition = child.localPosition;
                    instanceRootTransform.localScale = child.localScale;
                    instanceRootTransform.localEulerAngles = child.localEulerAngles;
                    var cityLightMapSync = instanceRoot.AddComponent<CityLightMapSync>();
                    cityLightMapSync.originRoot = child;
                    cityLightMapSync.IsSyncReflectionProbe = true;
                    instanceRoot.name = $"{variantInfo.VariantName}";

                    PrefabUtility.SaveAsPrefabAssetAndConnect(instanceRoot, 
                        $"Assets/Arts/Scene/InnerCity/Prefabs/Other/{variantInfo.VariantName}.prefab", InteractionMode.AutomatedAction);
                }
            }

            EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
        }

        private void CollectMapData(string mapConfigName, bool oneKey = false)
        {
            if (!string.IsNullOrEmpty(mapConfigName))
            {
                Undo.RecordObject(target, "PickChilds");
                var mapPath = "Assets/ResourcesAssets/Pve/Scene/" + mapConfigName + ".asset";
                mapData = AssetDatabase.LoadAssetAtPath<GgameSceneConfig>(mapPath);
                if (mapData != null)
                {
                    var mapDataPath = "Assets/ResourcesAssets/Pve/Scene/" + mapConfigName + "_separateData.asset";
                    var oldMapConfig = AssetDatabase.LoadAssetAtPath<SceneSeparateManagerData>(mapDataPath);

                    bool generate = false;
                    if (oldMapConfig != null)
                    {
                        if (EditorUtility.DisplayDialog("警告", "已经存在数据，是否覆盖？", "确定", "取消"))
                        {
                            generate = true;
                        }
                    }
                    else
                    {
                        generate = true;
                    }

                    if (generate)
                    {
                        var m_TargetData = CreateInstance<SceneSeparateManagerData>();

                        m_TargetData.PrefabRootPath = $"{sceneRootPath}{mapConfigName}Prefabs/";
                        bool success = PickChilds(m_TargetData);
                        if (success)
                        {
                            m_Target.sceneData = m_TargetData;
                            m_TargetData.DetectorSize = m_Target.DetectorSize;
                            m_TargetData.CameraOffset = m_Target.CameraOffset;
                            m_TargetData.DetectorOffset = m_Target.DetectorOffset;
                            //m_TargetData.mapData = mapData;

                            // 路径点
                            var wayPaths = UnityEngine.Object.FindObjectsOfType(typeof(NpcWayPath));
                            m_Target.sceneData.wayPaths = new List<NpcWayPathData>();
                            for (int i = 0; i < wayPaths.Length; i++)
                            {
                                m_Target.sceneData.wayPaths.Add((wayPaths[i] as NpcWayPath).GetData());
                            }

                            // 红绿灯
                            GameObject trafficLight = GameObject.Find("TrafficLight");
                            if (trafficLight != null)
                            {
                                TrafficLight[] trafficLights = trafficLight.GetComponentsInChildren<TrafficLight>();
                                if (trafficLights != null)
                                {
                                    foreach (var light in trafficLights)
                                    {
                                        light.OnSaved();
                                    }
                                }

                                // TODO 配上场景路径
                                PrefabUtility.SaveAsPrefabAsset(trafficLight,
                                    Application.dataPath + "/ResourcesAssets/Prefabs/NpcFramework/TrafficLight.prefab");
                            }

                            AssetDatabase.CreateAsset(m_TargetData, mapDataPath);
                            //删除所有子节点
                            int childCount = m_Target.transform.childCount;
                            for (int i = 0; i < childCount; i++)
                            {
                                GameObject.DestroyImmediate(m_Target.transform.GetChild(0).gameObject);
                            }

                            //从配置文件载入所有子物件
                            RevertAllChildFromAsset(true);
                            cacheEditor = UnityEditor.Editor.CreateEditor(m_Target.sceneData);

                            AssetDatabase.SaveAssets();

                            if (!oneKey)
                            {
                                EditorUtility.DisplayDialog("", "导出地图配置数据成功", "关闭");
                            }
                        }
                    }
                }
                else
                {
                    EditorUtility.DisplayDialog("错误", "请先执行收集场景数据", "关闭");
                }
            }
            else
            {
                EditorUtility.DisplayDialog("Error", "请填写争取的地图配置文件名", "关闭");
            }
        }

        private void RevertAllChildFromAsset(bool export = false)
        {
            if (m_Target.sceneData._loadObjects != null)
            {

                GameObject dynamicObj = new GameObject("DynamicObjs");
                dynamicObj.transform.parent = m_Target.transform;
                for (int i = 0; i < m_Target.sceneData._loadObjects.Length; i++)
                {
                    var o = m_Target.sceneData._loadObjects[i];
                    o.Generate(dynamicObj.transform);
                }
            }
            if (m_Target.sceneData._staticObjects != null)
            {
                GameObject staticObj = new GameObject("StaticObjs");
                staticObj.transform.parent = m_Target.transform;

                for (int i = 0; i < m_Target.sceneData._staticObjects.Length; i++)
                {
                    var o = m_Target.sceneData._staticObjects[i];
                    o.Generate(staticObj.transform, true);
                }
            }

            if (m_Target.sceneData.npcPoints != null)
            {
                GameObject npcPoint = GameObject.Find("NpcPoint");

                if (npcPoint)
                {
                    GameObject.DestroyImmediate(npcPoint);
                }
                npcPoint = new GameObject("NpcPoint");
                npcPoint.transform.SetSiblingIndex(2);
                Dictionary<int, NpcBrithPointData> dictionary = new Dictionary<int, NpcBrithPointData>();
                foreach (var data in m_Target.sceneData.allPointData)
                {
                    dictionary.Add(data.Index, data);
                }
                int index = 1000000;
                for (int i = 0; i < m_Target.sceneData.npcPoints.Count; i++)
                {
                    GameObject point = new GameObject("point" + i + "  " + m_Target.sceneData.npcPoints[i].SceneObjType);
                    point.transform.position = m_Target.sceneData.npcPoints[i].Position;
                    point.transform.forward = m_Target.sceneData.npcPoints[i].BrithPointData.Forward;
                    var bindData = point.AddComponent<ScceneDataBind>();
                    bindData.Index = index;

                    index++;
                    bindData.ObjType = m_Target.sceneData.npcPoints[i].BrithPointData.ObjType;
                    bindData.BrithPointData = m_Target.sceneData.npcPoints[i].BrithPointData;
                    bindData.GroupId = m_Target.sceneData.npcPoints[i].BrithPointData.GroupId;
                    bindData.TriggerSize = m_Target.sceneData.npcPoints[i].BrithPointData.TriggerSize;
                    bindData.EventName = m_Target.sceneData.npcPoints[i].BrithPointData.EventName;
                    bindData.IsNpcEvent = m_Target.sceneData.npcPoints[i].BrithPointData.IsNpcEvent;
                    bindData.IsDeleteByView = m_Target.sceneData.npcPoints[i].BrithPointData.IsDeleteByView;
                    bindData.NpcBornProbability = m_Target.sceneData.npcPoints[i].BrithPointData.NpcBornProbability;
                    point.transform.SetParent(npcPoint.transform);
                    if (m_Target.sceneData.npcPoints[i].BrithPointData.ChildBirthPoint != null && m_Target.sceneData.npcPoints[i].BrithPointData.ChildBirthPoint.Length > 0)
                    {
                        for (int j = 0; j < m_Target.sceneData.npcPoints[i].BrithPointData.ChildBirthPoint.Length; j++)
                        {
                            GameObject childPoint = new GameObject("childPoint" + j);
                            childPoint.transform.SetParent(point.transform);
                            int childPointDataIndex = m_Target.sceneData.npcPoints[i].BrithPointData.ChildBirthPoint[j];
                            var childPointData = dictionary[childPointDataIndex];
                            var childSceneData = childPoint.AddComponent<ScceneDataBind>();
                            childSceneData.Index = index;
                            childSceneData.ObjType = childPointData.ObjType;
                            childSceneData.BrithPointData = childPointData;
                            childPoint.transform.position = childPointData.Position;
                            childPoint.transform.forward = childPointData.Forward;
                            childSceneData.GroupId = childPointData.GroupId;
                            childSceneData.IsNpcEvent = childPointData.IsNpcEvent;
                            childSceneData.IsDeleteByView = childPointData.IsDeleteByView;
                            index++;
                        }
                    }
                }
            }

            Dictionary<int, NpcWayPath> wayPathDic = new Dictionary<int, NpcWayPath>();

            if (m_Target.sceneData.wayPaths != null && m_Target.sceneData.wayPaths.Count > 0)
            {
                GameObject wayRoot = GameObject.Find("NpcWayPath");
                if (wayRoot != null)
                {
                    GameObject.DestroyImmediate(wayRoot);
                }
                wayRoot = new GameObject("NpcWayPath");
                wayRoot.transform.SetSiblingIndex(1);

                for (int i = 0; i < m_Target.sceneData.wayPaths.Count; i++)
                {
                    NpcWayPath npcWayPath = RevertPath(m_Target.sceneData.wayPaths[i]);
                    wayPathDic.Add(npcWayPath.WayID, npcWayPath);
                }
            }

            // 红绿灯        
            GameObject trafficLight = GameObject.Find("TrafficLight");
            if (!export)
            {
                if (trafficLight != null)
                {
                    GameObject.DestroyImmediate(trafficLight);
                }

                trafficLight = GameObject.Instantiate(AssetDatabase.LoadAssetAtPath<GameObject>("Assets/ResourcesAssets/Prefabs/NpcFramework/TrafficLight.prefab"));

                if (trafficLight)
                {
                    trafficLight.transform.name = "TrafficLight";
                    trafficLight.transform.SetSiblingIndex(3);

                    TrafficLight[] trafficLights = trafficLight.GetComponentsInChildren<TrafficLight>();

                    if (trafficLights != null)
                    {
                        foreach (var light in trafficLights)
                        {
                            light.OnSaved();

                            foreach (var pointMap in light.waitPointMaps)
                            {
                                NpcWayPoint wayPoint = wayPathDic[pointMap.WayPathID].WayPoints[pointMap.PointIndex];
                                pointMap.WayPoint = wayPoint;
                                wayPoint.TrafficLight = light;
                            }

                            foreach (var pointMap in light.innerPointMaps)
                            {
                                NpcWayPoint wayPoint = wayPathDic[pointMap.WayPathID].WayPoints[pointMap.PointIndex];
                                pointMap.WayPoint = wayPoint;
                            }
                        }
                    }

                }
            }
            else
            {
                if (trafficLight != null)
                {
                    TrafficLight[] trafficLights = trafficLight.GetComponentsInChildren<TrafficLight>();

                    if (trafficLights != null)
                    {
                        foreach (var light in trafficLights)
                        {
                            light.OnSaved();

                            foreach (var pointMap in light.waitPointMaps)
                            {
                                NpcWayPoint wayPoint = wayPathDic[pointMap.WayPathID].WayPoints[pointMap.PointIndex];
                                pointMap.WayPoint = wayPoint;
                                wayPoint.TrafficLight = light;
                            }

                            foreach (var pointMap in light.innerPointMaps)
                            {
                                NpcWayPoint wayPoint = wayPathDic[pointMap.WayPathID].WayPoints[pointMap.PointIndex];
                                pointMap.WayPoint = wayPoint;
                            }
                        }
                    }
                }
            }


        }

        public NpcWayPath RevertPath(NpcWayPathData pathData)
        {
            GameObject wayRoot = GameObject.Find("NpcWayPath");
            Transform pathObj = new GameObject("Path" + pathData.WayID).transform;
            pathObj.transform.parent = wayRoot.transform;

            NpcWayPath npcWayPath = pathObj.gameObject.AddComponent<NpcWayPath>();
            npcWayPath.IsLoop = pathData.IsLoop;
            npcWayPath.WayID = pathData.WayID;
            npcWayPath.HaveWidth = true;
            npcWayPath.WayPathType = pathData.WayPathType;
            npcWayPath.WayPoints = new List<NpcWayPoint>();

            for (int i = 0; i < pathData.WayPoints.Count; i++)
            {
                Transform point = new GameObject(i.ToString()).transform;
                point.parent = pathObj.transform;

                NpcWayPoint npcWayPoint = point.gameObject.AddComponent<NpcWayPoint>();
                npcWayPoint.WayPath = npcWayPath;

                var data = pathData.WayPoints[i];

                npcWayPoint.width = data.Width;
                npcWayPoint.Index = data.Index;
                npcWayPoint.transform.position = data.Position;
                npcWayPoint.transform.forward = data.Forward;
                npcWayPoint.transform.right = data.Right;
                npcWayPoint.IsGenerateCar = data.IsGenerateCar;
                npcWayPoint.IsGenerateNpc = data.IsGenerateNpc;
                npcWayPoint.BTreePath = data.BTreeName;
                npcWayPath.WayID = data.WayId;

                npcWayPath.WayPoints.Add(npcWayPoint);
            }

            for (int i = 0; i < pathData.WayPoints.Count; i++)
            {
                var data = pathData.WayPoints[i];
                if (data.NextIndex != ConstValue.INVALID_INDEX)
                {
                    npcWayPath.WayPoints[i].NextWayPoint = npcWayPath.WayPoints[data.NextIndex];
                }

                if (data.PrevIndex != ConstValue.INVALID_INDEX)
                {
                    npcWayPath.WayPoints[i].PrevWayPoint = npcWayPath.WayPoints[data.PrevIndex];
                }

                if (data.BranchIndex != null)
                {
                    foreach (var pointData in data.BranchIndex)
                    {
                        npcWayPath.WayPoints[i].branchPoints.Add(npcWayPath.WayPoints[pointData.Index]);
                        npcWayPath.WayPoints[pointData.Index].branchRatio = pointData.Ratio;
                        npcWayPath.WayPoints[pointData.Index].branchType = pointData.BranchType;
                    }
                }
            }

            return npcWayPath;
        }

        private bool PickChilds(SceneSeparateManagerData sceneData)
        {

            // if (m_Target.transform.childCount == 0)
            // {
            //     EditorUtility.DisplayDialog("错误", "节点下没有物体", "关闭");
            //     return false;
            // }
            List<SceneObjectDisplay> sceneObjectDisplays = new List<SceneObjectDisplay>();
            List<SceneObjectInfo> sceneObjectInfos = new List<SceneObjectInfo>();
            List<SceneNpcBirthPoint> pointList = new List<SceneNpcBirthPoint>();
            Dictionary<int, NpcBrithPointData> npcPointDataDictionary = new Dictionary<int, NpcBrithPointData>();
            var npt = GameObject.Find("NpcPoint");
            if (npt)
            {
                Transform npcPoint = npt.transform;
                PickAllBirthPoint(npcPoint, npcPointDataDictionary);
                PickBirthPointById(npcPoint, pointList, npcPointDataDictionary);
            }

            // 所有预制体的路径先存放起来，各个物件信息只保留一个序号
            sceneData.PrefabPaths = mapData.PrefabPaths.Select(x=>x.Replace(sceneData.PrefabRootPath, "")).ToArray();
            prefabPathAndIndexMap = new Dictionary<string, int>();
            for (var i = 0; i < mapData.PrefabPaths.Count; i++)
            {
                prefabPathAndIndexMap[mapData.PrefabPaths[i]] = i;
            }

            // 所有MeshRenderer的光照信息也统一存放，各个物件只保留一个起始序号和长度
            meshRendererDataList = new List<MeshRendererData>();

            PickChildById(m_Target.transform, sceneObjectDisplays, sceneObjectInfos);

            sceneData.MeshRendererDataList = meshRendererDataList.ToArray();

            float maxX, maxY, maxZ, minX, minY, minZ;
            maxX = maxY = maxZ = -Mathf.Infinity;
            minX = minY = minZ = Mathf.Infinity;

#if false
            if (sceneObjectDisplays.Count > 0)
            {
                List<SceneObjectDisplay> staticList = new List<SceneObjectDisplay>();
                List<SceneObjectDisplay> dynamicList = new List<SceneObjectDisplay>();
                foreach (var item in sceneObjectDisplays)
                {
                    switch (item.SceneObjType)
                    {
                        case SceneObjType.Static:
                            staticList.Add(item);
                            break;
                        case SceneObjType.Dynamic:
                        case SceneObjType.StaticHqOnly:
                            dynamicList.Add(item);
                            break;
                    }
                }

                sceneData.loadObjects = dynamicList;
                sceneData.staticObjects = staticList;
            }
#endif

            if (sceneObjectInfos.Count > 0)
            {
                var staticList = new List<SceneObjectInfo>();
                var dynamicList = new List<SceneObjectInfo>();
                foreach (var sceneObjectInfo in sceneObjectInfos)
                {
                    switch (sceneObjectInfo.SceneObjType)
                    {
                        case SceneObjType.Static:
                            staticList.Add(sceneObjectInfo);
                            break;
                        case SceneObjType.Dynamic:
                        case SceneObjType.StaticHqOnly:
                            dynamicList.Add(sceneObjectInfo);
                            break;
                    }
                }

                sceneData._loadObjects = dynamicList.ToArray();
                sceneData._staticObjects = staticList.ToArray();
                sceneData.allPointData = npcPointDataDictionary.Values.ToList<NpcBrithPointData>();
            }

            //NPC生成点
            if (pointList.Count > 0)
            {
                List<SceneNpcBirthPoint> birthPointList = new List<SceneNpcBirthPoint>();
                foreach (var item in pointList)
                {
                    birthPointList.Add(item);
                }
                sceneData.npcPoints = birthPointList;
            }


            for (int i = 0; i < sceneObjectDisplays.Count; i++)
            {
                maxX = Mathf.Max(sceneObjectDisplays[i].Bounds.max.x, maxX);
                maxY = Mathf.Max(sceneObjectDisplays[i].Bounds.max.y, maxY);
                maxZ = Mathf.Max(sceneObjectDisplays[i].Bounds.max.z, maxZ);

                minX = Mathf.Min(sceneObjectDisplays[i].Bounds.min.x, minX);
                minY = Mathf.Min(sceneObjectDisplays[i].Bounds.min.y, minY);
                minZ = Mathf.Min(sceneObjectDisplays[i].Bounds.min.z, minZ);
            }
            Vector3 size = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
            Vector3 center = new Vector3(minX + size.x / 2, minY + size.y / 2, minZ + size.z / 2);
            sceneData.bounds = new Bounds(center, size);

            return true;
        }
        
        private void PickChildById(Transform transform, List<SceneObjectDisplay> sceneObjectList, List<SceneObjectInfo> sceneObjectInfos)
        {
            //是不是一个prefab
            var sceneDataBind = transform.GetComponent<ScceneDataBind>();
            if (sceneDataBind != null)
            {
                var sceneObjectDisplay = GetChildSceneObjectDisplay(transform, sceneDataBind);
                if (sceneObjectDisplay != null)
                    sceneObjectList.Add(sceneObjectDisplay);

                var sceneObjectInfo = GetChildSceneObjectInfo(transform, sceneDataBind);
                if (sceneObjectInfo != null)
                    sceneObjectInfos.Add(sceneObjectInfo);
            }
            else
            {
                for (int i = 0; i < transform.childCount; i++)
                {
                    PickChildById(transform.GetChild(i), sceneObjectList, sceneObjectInfos);
                }
            }
        }
        
        private void PickAllBirthPoint(Transform transform, Dictionary<int, NpcBrithPointData> npcPointDataList)
        {
            var scceneDataBinds = transform.GetComponentsInChildren<ScceneDataBind>();
            int index = 1000000;
            foreach (var dataBind in scceneDataBinds)
            {
                dataBind.Index = index;
                dataBind.BrithPointData.Index = index;
                npcPointDataList.Add(dataBind.Index, dataBind.BrithPointData);
                index++;
            }
        }
        
        private void PickBirthPointById(Transform transform, List<SceneNpcBirthPoint> birthPointList, Dictionary<int, NpcBrithPointData> npcPointDataDictionary)
        {
            //是不是一个prefab
            var obj = transform.GetComponent<ScceneDataBind>();
            if (obj != null && (obj.ObjType == SceneObjType.BirthPoint || obj.ObjType == SceneObjType.BirthPointParent || obj.ObjType == SceneObjType.NpcGroup || obj.ObjType == SceneObjType.Event))
            {

                var o = GetNpcBirthPoint(transform, obj);
                o.BrithPointData.ObjType = obj.ObjType;
                o.BrithPointData.Index = obj.Index;
                o.BrithPointData.NpcBornProbability = obj.NpcBornProbability;
                o.BrithPointData.RootName = obj.name;
                var boxC = transform.GetComponent<BoxCollider>();
                if (boxC)
                {
                    o.BrithPointData.checkCenter = boxC.center;
                    o.BrithPointData.checkSize = boxC.size;
                }
                
                if (o != null)
                    birthPointList.Add(o);
                if (obj.ObjType == SceneObjType.BirthPointParent)
                {
                    obj.BrithPointData.ChildBirthPoint = new int[transform.childCount];
                    for (int i = 0; i < obj.BrithPointData.ChildBirthPoint.Length; i++)
                    {
                        var childData = transform.GetChild(i).GetComponent<ScceneDataBind>();
                        obj.BrithPointData.ChildBirthPoint[i] = childData.Index;
                        var serializeChildData = npcPointDataDictionary[childData.Index];
                        serializeChildData.Index = childData.Index;
                        serializeChildData.Position = childData.transform.position;
                        serializeChildData.Forward = childData.transform.forward;
                        serializeChildData.ObjType = childData.ObjType;
                        serializeChildData.GroupId = childData.GroupId;
                        serializeChildData.IsNpcEvent = childData.IsNpcEvent;
                        serializeChildData.EventName = childData.EventName;
                        serializeChildData.TriggerSize = childData.TriggerSize;

                        var boxCollider = childData.transform.GetComponent<BoxCollider>();
                        if (boxCollider)
                        {
                            serializeChildData.checkCenter = boxCollider.center;
                            serializeChildData.checkSize = boxCollider.size;
                        }
                    }
                }
                else if (obj.ObjType == SceneObjType.NpcGroup)
                {
                    o.BrithPointData.GroupId = obj.GroupId;
                    o.BrithPointData.Index = obj.Index;
                }
                else if (obj.ObjType == SceneObjType.Event)
                {
                    o.BrithPointData.TriggerForward = obj.BrithPointData.TriggerForward;
                    o.BrithPointData.TriggerPosition = obj.BrithPointData.TriggerPosition;
                    o.BrithPointData.EventName = obj.EventName;
                    o.BrithPointData.TriggerSize = obj.TriggerSize;
                    o.BrithPointData.IsNpcEvent = obj.IsNpcEvent;
                    o.BrithPointData.Index = obj.Index;
                    obj.BrithPointData.ChildBirthPoint = new int[transform.childCount];
                    o.BrithPointData.EventId = obj.BrithPointData.EventId;

                    for (int i = 0; i < obj.BrithPointData.ChildBirthPoint.Length; i++)
                    {
                        var childData = transform.GetChild(i).GetComponent<ScceneDataBind>();
                        obj.BrithPointData.ChildBirthPoint[i] = childData.Index;
                        var serializeChildData = npcPointDataDictionary[childData.Index];
                        serializeChildData.Position = childData.transform.position;
                        serializeChildData.Forward = childData.transform.forward;
                        serializeChildData.ObjType = childData.ObjType;
                        serializeChildData.GroupId = childData.GroupId;
                        serializeChildData.IsNpcEvent = childData.IsNpcEvent;
                        serializeChildData.Index = childData.Index;
                        var boxCollider = childData.transform.GetComponent<BoxCollider>();
                        if (boxCollider)
                        {
                            serializeChildData.checkCenter = boxCollider.center;
                            serializeChildData.checkSize = boxCollider.size;
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < transform.childCount; i++)
                {
                    PickBirthPointById(transform.GetChild(i), birthPointList, npcPointDataDictionary);
                }
            }
        }

        private PrefabData GetChildmapDataByIndex(int index)
        {
            if (mapData)
            {
                if (index < mapData.PrefabDatas.Count)
                {
                    PrefabData prefabData = mapData.PrefabDatas[index];
                    prefabData.resPath = mapData.GetPrefabResPath(prefabData);
                    return prefabData;
                }
                return null;
            }
            Debug.LogError("mapData is null");
            return null;
        }

        private SceneNpcBirthPoint GetNpcBirthPoint(Transform transform, ScceneDataBind sscObj)
        {
            Bounds bounds = new Bounds(transform.position, Vector3.one);
            sscObj.BrithPointData.Forward = transform.forward;
            sscObj.BrithPointData.Position = transform.position;
            SceneNpcBirthPoint birthPoint = new SceneNpcBirthPoint(bounds, sscObj.ObjType, transform.position, sscObj.BrithPointData, sscObj.Index, transform.name);

            return birthPoint;
        }

        private SceneObjectDisplay GetChildSceneObjectDisplay(Transform transform, ScceneDataBind sscObj)
        {
            if (sscObj.Index < 0)
            {
                Debug.LogError("Index 无效");
            }
            List<MeshRenderer> renderers = transform.gameObject.GetComponent<PrefabMeshRenderCache>().MeshRenderers;
            if (renderers == null || renderers.Count == 0)
                return null;

            Vector3 min = renderers[0].bounds.min;
            Vector3 max = renderers[0].bounds.max;
            for (int i = 1; i < renderers.Count; i++)
            {
                min = Vector3.Min(renderers[i].bounds.min, min);
                max = Vector3.Max(renderers[i].bounds.max, max);
            }
            Vector3 size = max - min;
            Bounds bounds = new Bounds(min + size / 2, size);
            if (size.x <= 0)
                size.x = 0.2f;
            if (size.y <= 0)
                size.y = 0.2f;
            if (size.z <= 0)
                size.z = 0.2f;
            bounds.size = size;

            var prefabData = GetChildmapDataByIndex(sscObj.Index);
            if (prefabData != null)
            {
                var sceneObjectDisplay = new SceneObjectDisplay(
                    bounds,
                    transform,
                    sscObj.Index,
                    prefabData,
                    sscObj.IsStatic,
                    sscObj.ObjType);
                return sceneObjectDisplay;
            }

            UnityEngine.Debug.LogError("配置文件中没有这个索引的数据：" + sscObj.Index);
            return null;
        }

        private SceneObjectInfo GetChildSceneObjectInfo(Transform transform, ScceneDataBind sceneDataBind)
        {
            if (sceneDataBind.Index < 0)
            {
                Debug.LogError("Index 无效");
            }
            List<MeshRenderer> renderers = transform.gameObject.GetComponent<PrefabMeshRenderCache>().MeshRenderers;
            if (renderers == null || renderers.Count == 0)
                return null;

            Vector3 min = renderers[0].bounds.min;
            Vector3 max = renderers[0].bounds.max;
            for (int i = 1; i < renderers.Count; i++)
            {
                min = Vector3.Min(renderers[i].bounds.min, min);
                max = Vector3.Max(renderers[i].bounds.max, max);
            }
            Vector3 size = max - min;
            Bounds bounds = new Bounds(min + size / 2, size);
            if (size.x <= 0)
                size.x = 0.2f;
            if (size.y <= 0)
                size.y = 0.2f;
            if (size.z <= 0)
                size.z = 0.2f;
            bounds.size = size;

            var prefabData = GetChildmapDataByIndex(sceneDataBind.Index);
            if (prefabData != null)
            {
                int startIndex = meshRendererDataList.Count;
                int count = prefabData.MeshRendererDatas.Count;
                meshRendererDataList.AddRange(prefabData.MeshRendererDatas);

                var sceneObjectInfo = new SceneObjectInfo(
                    bounds,
                    transform,
                    sceneDataBind.Index,
                    prefabPathAndIndexMap[prefabData.resPath], 
                    startIndex, count,
                    sceneDataBind.IsStatic,
                    sceneDataBind.ObjType);
                return sceneObjectInfo;
            }

            UnityEngine.Debug.LogError("配置文件中没有这个索引的数据：" + sceneDataBind.Index);
            return null;
        }

        static Vector3 centerPosition;
        private Dictionary<string, int> prefabPathAndIndexMap;
        private List<MeshRendererData> meshRendererDataList;
    }
}
